package com.hwd.gmall.oauth.service.impl;

import com.hwd.gmall.oauth.service.LoginService;
import com.hwd.gmall.oauth.util.AuthToken;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Base64;
import java.util.Map;

/**
 * 自定义的登录服务实现类
 *
 * @author 黄伟东/Victor
 * @date 2022/5/4 20:01
 */
@Service
public class LoginServiceImpl implements LoginService {

    /** 发送http请求的客户端对象 */
    @Resource
    private RestTemplate restTemplate;

    /** 负载均衡的客户端对象 */
    @Resource
    private LoadBalancerClient loadBalancerClient;

    @Value("${auth.clientId}")
    private String clientId;

    @Value("${auth.clientSecret}")
    private String clientSecret;

    /**
     * 自定义登录
     *
     * @param username 用户名
     * @param password 密码
     * @return com.hwd.gmall.oauth.util.AuthToken
     */
    @Override
    public AuthToken login(String username, String password) {

        // 检验用户名和密码是否为空
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            throw new RuntimeException("用户名或密码不能为空！");
        }

        // 包装body中的三个参数：用户名 密码 模式
        MultiValueMap<String, String> body = new HttpHeaders();
        body.add("grant_type", "password");
        body.add("username", username);
        body.add("password", password);

        // 包装客户端id和客户端秘钥
        MultiValueMap<String, String> headers = new HttpHeaders();
        headers.add("Authorization", getHead());

        // 向认证服务发送认证请求
        // 以负载均衡的方式，从注册中心中以服务名字获取服务的实例
        ServiceInstance serviceInstance = loadBalancerClient.choose("service-oauth");
        String url = serviceInstance.getUri().toString() + "/oauth/token";
//        String url = "http://localhost:9001/oauth/token";
        ResponseEntity<Map> exchange =
                restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(body, headers), Map.class);

        // 获取请求的结果解析令牌的数据
        Map<String, String> result = exchange.getBody();

        // 返回结果
        AuthToken authToken = new AuthToken();
        if (result != null) {
            authToken.setAccessToken(result.get("access_token"));
            authToken.setRefreshToken(result.get("refresh_token"));
            authToken.setJti(result.get("jti"));
        }

        return authToken;
    }

    /**
     * 构建请求头中的参数
     *
     * @return java.lang.String
     */
    private String getHead() {

        // 客户端id + : + 客户端秘钥
        String head = clientId + ":" + clientSecret;

        // 进行Base64加密
        byte[] encode = Base64.getEncoder().encode(head.getBytes());

        // 返回Basic + 空格 + 加密结果
        return "Basic " + new String(encode);
    }
}
